Australia’s coastline is facing increasing pressures from erosion, exacerbated by rising sea levels and extreme weather events. To determine which parts of the coast are vulnerable, it’s crucial to identify which areas are protected by coastal structures such as sea walls, groynes, and levees. Unfortunately, while few states, such as Victoria and Tasmania, offer a detailed and publicly accessible dataset of its coastal protection structures, there is currently no equivalent at a national level. A comprehensive national dataset is urgently needed to assess the risks to Australia’s coastlines and provide guidance for protecting vulnerable regions.
This is where the National Environmental Science Program (NESP) comes in. As part of its efforts, NESP knowledge brokers are reaching out to each state government to inquire about available spatial data on coastal protection structures. These datasets would ideally include vital information such as the location, height, and type of each structure. While Victoria and Tasmania’s data is readily available, it isn’t regularly updated, and it appears that in many other states, this information is either not centralised or may be held at the local government level.
A recent report from the Insurance
Council of Australia, titled Actions of the Sea, highlights the need
for consistency in how coastal defence data is gathered and shared. It
recommends that state and local governments develop spatial databases of
coastal defences according to a standard framework.
The framework should capture key details, such as:
To help fill the current gaps in our knowledge of coastal defences, this blog delves into the potential of citizen science. One valuable resource is OpenStreetMap (OSM), where users around the world contribute geographic information. This includes mapping coastal structures in Australia, and while it is not yet comprehensive, it serves as a useful starting point for understanding where protections exist—and where they do not. Through exploring OSM contributions, we aim to inform efforts to collect standardised data and make it more accessible to coastal researchers, engineers, and managers.
By highlighting gaps in coastal defence data, this blog complements NESP’s knowledge broker outreach. Together, these efforts will strengthen our understanding of coastal protection, helping to pinpoint the areas most vulnerable to erosion and guide future efforts to safeguard Australia’s shores.
Below, we present R code analysis of the publicly
available data. If you scroll to the end, you’ll find a interactive map
comparing the national OSM and Victoria’s data, along with a
Call to Action: Get Involved! to support our efforts to
assemble a national dataset of coastal structures.
The sections of code below provide a working example of processes geospatial data on coastal structures sourced from OpenStreetMap (OSM).
The key-value pairs used to filter relevant OSM data include:
1. man_made = groyne: A rigid structure built
from the shore to interrupt water flow and limit sediment movement,
often used to prevent beach erosion. https://wiki.openstreetmap.org/wiki/Tag:man_made%3Dgroyne
2. man_made = embankment: An artificial steep slope
built along coastlines or rivers to prevent water from overflowing and
flooding adjacent land. https://wiki.openstreetmap.org/wiki/Tag:man_made%3Dembankment
3. man_made = dyke: A raised structure designed to
restrict water flow, typically built to protect coastal land from
flooding. https://wiki.openstreetmap.org/wiki/Tag:man_made%3Ddyke
4. man_made = quay: A solid platform along the
shore or a riverbank, built for loading and unloading ships. https://wiki.openstreetmap.org/wiki/Tag:man_made%3Dquay
5. man_made = breakwater: A structure built
offshore to protect a coast or harbour from the force of waves. https://wiki.openstreetmap.org/wiki/Tag:man_made%3Dbreakwater
6. man_made = pier: A raised platform extending
into the sea or a body of water, commonly used for docking boats or
recreational purposes. https://wiki.openstreetmap.org/wiki/Tag:man_made%3Dpier
7. bridge = boardwalk: A wooden or raised path
usually found along coastal areas, providing pedestrian access over
marshes or water. https://wiki.openstreetmap.org/wiki/Tag:bridge%3Dboardwalk
8. barrier = retaining_wall: A wall constructed to
prevent soil or coastal land from eroding or sliding into the water. https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dretaining_wall
9. barrier = wall: A generic wall structure that
can also be used along coasts to define property or act as flood
protection. https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dwall
10. wall = flood_wall: A specific type of wall
designed to keep coastal or river waters from flooding inland areas. https://wiki.openstreetmap.org/wiki/Tag:wall%3Dflood_wall
11. wall = seawall: A structure built parallel to
the coast to protect the shore from erosion and storm surges. https://wiki.openstreetmap.org/wiki/Tag:wall%3Dseawall
12. emergency = lifeguard: A designated spot or
station for lifeguards, typically located on beaches to ensure water
safety. https://wiki.openstreetmap.org/wiki/Tag:emergency%3Dlifeguard
13. leisure = slipway: A ramp leading into the
water, used for launching or retrieving boats. https://wiki.openstreetmap.org/wiki/Tag:leisure%3Dslipway
For each of the key-value pairs, the OSM Overpass API was used to query and extract GeoJSON files for these 13 key-value pairs: - Overpass Turbo Query: https://overpass-turbo.eu/?template=key-value&key=man_made&value=groyne#
The script performs the following steps:
The output is a GeoPackage file containing the filtered and processed coastal structures along the Australian coastline. This file can be used for further analysis or mapping of coastal defences in Australia.
suppressPackageStartupMessages(library(leaflet))
suppressPackageStartupMessages(library(terra))
## Warning: package 'terra' was built under R version 4.4.1
suppressPackageStartupMessages(library(sf))
suppressPackageStartupMessages(library(dplyr))
datadir = "data/"
The coast was made via adding a 200m buffer around a 100m OSM coastline of Australia from the code in https://doi.org/10.25919/mapj-bq95
aus_coast = vect(paste0(datadir,"OSM_AUScoastBuffer200m",".gpkg"))
read in the OSM geoJSONs download on 29th Aug 2024
OSM_geofiles = list.files(paste0(datadir,"OSM_shapes_20240829"),full.names = TRUE)
OSM_geofiles = paste0(datadir,"OSM_shapes_20240829/export (",1:13,").geojson")
filetxt <- c(
"man_made:groyne",
"man_made:embankment",
"man_made:dyke",
"man_made:quay",
"man_made:breakwater",
"man_made:pier",
"bridge:boardwalk",
"barrier:retaining_wall",
"barrier:wall",
"wall:flood_wall",
"wall:seawall",
"emergency:lifeguard",
"leisure:slipway"
)
#open street map coastal geojsons
geoms = lapply(OSM_geofiles,function(x) sapply(svc(x),function(x) geomtype(x)))
n = length(OSM_geofiles)
#some shapes are lines, here is a list of lines
OSM_cps_pl = lapply(1:n,function(x) {if(any(geoms[[x]]=="polygons")) {y=NULL;y = svc(OSM_geofiles[x])[[which(geoms[[x]]=="polygons")]];y$filetype = filetxt[x];y$drawn = "polygons";y}})
#some shapes are polygons, here is a list of polygons
OSM_cps_ll = lapply(1:n,function(x) {if(any(geoms[[x]]=="lines")) {y=NULL;y = svc(OSM_geofiles[x])[[which(geoms[[x]]=="lines")]];y$filetype = filetxt[x];y$drawn = "lines";y}})
Clean the lists and convert lines to polygons a with width of 1m.
OSM_cps_p = vect(OSM_cps_pl[which(!sapply(OSM_cps_pl,is.null))])
touch = relate(OSM_cps_p,aus_coast,"intersects",pairs = TRUE)
OSM_cps_p = OSM_cps_p[unique(touch[,1])]
OSM_cps_l = vect(OSM_cps_ll[which(!sapply(OSM_cps_ll,is.null))])
touch = relate(OSM_cps_l,aus_coast,"intersects",pairs = TRUE)
OSM_cps_l = buffer(OSM_cps_l[unique(touch[,1])],0.5)
Bring the datasets together and keep only the shapes within 200km of the OSM coast.
OSM_cps_coast = rbind(OSM_cps_l,OSM_cps_p)
OSM_cps_coast = buffer(OSM_cps_coast,0)
#OSM_cps_coast = OSM_cps_coast[which(is.valid(OSM_cps_coast))]
#cols_to_keep <- as.numeric(which(!sapply(OSM_cps_coast, function(x) all(is.na(x) | x == ""))))
#OSM_cps_coast_out <- OSM_cps_coast[,cols_to_keep]
#OSM_cps_coast_out <- OSM_cps_coast_out[,-2]
OSM_cps_coast_out = OSM_cps_coast
values(OSM_cps_coast_out) = NA
OSM_cps_coast_out$filetype = OSM_cps_coast$filetype
OSM_cps_coast_out$FID = 1:length(OSM_cps_coast_out)
writeVector(OSM_cps_coast_out,paste0(datadir,"OSM_coastalStructures.geojson"), filetype = "GeoJSON",overwrite=TRUE)
Because some shapes are lines and some polygons, lines were converted to a 1m wide polygon
calculate_area_summary <- function(vect_data, group_by_col) {
# Calculate area in square meters
vect_data$area_m <- expanse(vect_data, unit = "m")
# Group by the specified column and summarise
summary_stats <- values(vect_data) %>%
group_by(.data[[group_by_col]]) %>%
summarise(
count = n(),
mean_area_m = round(mean(area_m), 2),
min_area_m = round(min(area_m), 2),
max_area_m = round(max(area_m), 2),
std_area_m = round(sd(area_m), 2)
)
# Rename the grouping column for clarity
names(summary_stats)[1] <- group_by_col
# Display the summary statistics
return(knitr::kable(summary_stats))
}
calculate_area_summary(OSM_cps_coast_out,"filetype")
| filetype | count | mean_area_m | min_area_m | max_area_m | std_area_m |
|---|---|---|---|---|---|
| barrier:retaining_wall | 365 | 138.63 | 3.21 | 12949.15 | 726.77 |
| barrier:wall | 491 | 251.97 | 1.02 | 29228.01 | 1644.05 |
| bridge:boardwalk | 326 | 80.04 | 1.30 | 1004.98 | 122.93 |
| emergency:lifeguard | 219 | 433.17 | 4.90 | 1891.47 | 371.91 |
| leisure:slipway | 330 | 52.24 | 5.66 | 2938.12 | 169.15 |
| man_made:breakwater | 319 | 4006.00 | 9.12 | 51280.12 | 7145.04 |
| man_made:dyke | 11 | 233.38 | 9.87 | 1059.48 | 309.43 |
| man_made:embankment | 67 | 2530.07 | 6.71 | 76344.93 | 9448.60 |
| man_made:groyne | 200 | 624.30 | 5.92 | 25392.62 | 2132.96 |
| man_made:pier | 5380 | 380.84 | 1.18 | 122943.66 | 2890.42 |
| man_made:quay | 5 | 3305.54 | 189.55 | 15513.92 | 6825.05 |
| wall:flood_wall | 1 | 321.83 | 321.83 | 321.83 | NA |
| wall:seawall | 1 | 321.83 | 321.83 | 321.83 | NA |
The Victoria Governments has published the most complete public database of coastal structures https://discover.data.vic.gov.au/dataset/coastal-protection-structures. Here we compare the OSM shapes to the victorian Database.
vicdata <- project(buffer(vect("data/victoria/COASTS"),0.5),OSM_cps_coast_out)
calculate_area_summary(crop(OSM_cps_coast_out,ext(vicdata)),"filetype")
| filetype | count | mean_area_m | min_area_m | max_area_m | std_area_m |
|---|---|---|---|---|---|
| barrier:retaining_wall | 175 | 73.43 | 3.21 | 489.02 | 79.50 |
| barrier:wall | 102 | 200.08 | 2.49 | 11937.74 | 1183.16 |
| bridge:boardwalk | 81 | 76.25 | 2.41 | 439.89 | 97.13 |
| emergency:lifeguard | 23 | 563.52 | 72.78 | 1821.86 | 407.86 |
| leisure:slipway | 65 | 62.13 | 7.86 | 617.53 | 90.33 |
| man_made:breakwater | 74 | 1486.92 | 15.44 | 20808.66 | 3475.79 |
| man_made:groyne | 47 | 344.93 | 13.40 | 1739.68 | 398.43 |
| man_made:pier | 542 | 447.89 | 1.53 | 42608.79 | 2210.52 |
| man_made:quay | 2 | 277.15 | 189.55 | 364.74 | 123.88 |
The Victorian datasets has some similar (Groyne and Breakwater), and some different (Seawall), label types for features. It was
calculate_area_summary(vicdata,"STRUC_TYPE")
| STRUC_TYPE | count | mean_area_m | min_area_m | max_area_m | std_area_m |
|---|---|---|---|---|---|
| Breakwater | 62 | 150.31 | 8.16 | 1043.25 | 191.26 |
| Groyne | 355 | 29.09 | 2.00 | 217.52 | 30.81 |
| Other | 15 | 63.80 | 10.22 | 273.92 | 78.78 |
| Revetment | 366 | 174.99 | 2.78 | 2357.83 | 275.89 |
| Seawall | 635 | 143.55 | 3.70 | 2608.48 | 206.79 |
| Unknown | 57 | 67.82 | 1.68 | 484.67 | 92.24 |
| Wharf_commercial | 21 | 649.55 | 21.78 | 2042.68 | 549.61 |
| Wharf_noncommercial | 62 | 188.41 | 10.18 | 1643.46 | 244.68 |
THe tasmanian data was sourced from https://www.thelist.tas.gov.au/app/content/data/geo-meta-data-record?detailRecordUID=195c6de2-53e8-4792-84fa-5ab1590b2f8c
Here is a summary of OSM data for Tasmania
tas_line = vect(paste0(datadir,"tasmania/built_infrastructure_line_statewide.shp"))
tas_poly = vect(paste0(datadir,"tasmania/built_infrastructure_poly_statewide.shp"))
tasdata = project(rbind(buffer(tas_line[tas_line$INFTY1_TXT == "Marine"],0.5),tas_poly[tas_poly$INFTY1_TXT == "Marine"]),OSM_cps_coast_out)
tasdata
## class : SpatVector
## geometry : polygons
## dimensions : 1087, 13 (geometries, attributes)
## extent : 143.8429, 148.3482, -43.57745, -39.47411 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## names : INFRA_ID INFRA_TY1 INFRA_TY2 INFTY1_TXT INFTY2_TXT NOM_REG_NO
## type : <int> <int> <int> <chr> <chr> <chr>
## values : 522 3 11 Marine Breakwater NA
## 1626 3 11 Marine Breakwater NA
## 2383 3 11 Marine Breakwater NA
## NAME DESCRIPT UFI CREATED_ON (and 3 more)
## <chr> <chr> <chr> <chr>
## NA NA {9b315dc8-9f30~ 2007-06-08 10:~
## NA NA {14f67c58-5a48~ 2016-07-05 11:~
## NA NA {f4ed05a7-ddfb~ 2011-02-23 12:~
calculate_area_summary(crop(OSM_cps_coast_out,ext(tasdata)),"filetype")
| filetype | count | mean_area_m | min_area_m | max_area_m | std_area_m |
|---|---|---|---|---|---|
| barrier:retaining_wall | 10 | 106.36 | 8.12 | 530.62 | 154.01 |
| barrier:wall | 97 | 49.35 | 3.47 | 457.84 | 64.69 |
| bridge:boardwalk | 8 | 81.94 | 1.86 | 331.78 | 107.19 |
| emergency:lifeguard | 1 | 97.43 | 97.43 | 97.43 | NA |
| leisure:slipway | 44 | 41.62 | 9.27 | 321.49 | 53.62 |
| man_made:breakwater | 13 | 4490.11 | 28.88 | 27201.69 | 8783.81 |
| man_made:dyke | 5 | 34.37 | 9.87 | 75.33 | 25.96 |
| man_made:pier | 618 | 202.48 | 2.07 | 14400.81 | 1023.91 |
| wall:flood_wall | 1 | 321.83 | 321.83 | 321.83 | NA |
| wall:seawall | 1 | 321.83 | 321.83 | 321.83 | NA |
Here is a summary of the tasmanian data https://www.thelist.tas.gov.au/app/content/data/geo-meta-data-record?detailRecordUID=195c6de2-53e8-4792-84fa-5ab1590b2f8c
calculate_area_summary(tasdata,"INFTY2_TXT")
| INFTY2_TXT | count | mean_area_m | min_area_m | max_area_m | std_area_m |
|---|---|---|---|---|---|
| Boat Ramp | 6 | 170.42 | 43.76 | 365.80 | 139.88 |
| Breakwater | 24 | 468.13 | 6.33 | 8912.04 | 1803.60 |
| Fish Farm | 59 | 486001.57 | 1118.94 | 15979652.44 | 2068338.82 |
| Groyne | 3 | 34.57 | 19.24 | 44.68 | 13.51 |
| Jetty | 711 | 112.35 | 4.12 | 3112.33 | 232.28 |
| Marina | 53 | 593.39 | 21.68 | 2785.99 | 714.13 |
| Navigation Buoy | 3 | 16.82 | 11.63 | 19.42 | 4.50 |
| Oyster Bed | 131 | 74867.23 | 472.94 | 392379.11 | 81068.05 |
| Pier | 4 | 2378.22 | 646.62 | 5664.50 | 2246.43 |
| Slipway | 52 | 341.19 | 6.41 | 8816.33 | 1230.67 |
| Wharf | 41 | 5291.02 | 66.68 | 124323.72 | 19735.55 |
Here we map the Victorian, Tasmanian and OSM shapes starting around Geelong in Western Port Phillip Bay. But you are free to zoom around the state or Tasmania, or country and click on a structure to find more info.
# Convert to 'sf' objects for leaflet compatibility
vicdata_sf <- st_as_sf(vicdata)
OSM_cps_sf <- st_as_sf(OSM_cps_coast_out)
tasdata_sf <- st_as_sf(tasdata)
# Define the bounding box for Geelong (approximate coordinates)
geelong_bbox <- st_bbox(c(xmin = 144.30, ymin = -38.25, xmax = 144.45, ymax = -38.10), crs = st_crs(4326))
# Create the leaflet map
leaflet() %>%
addProviderTiles("OpenStreetMap", group = "OpenStreetMap") %>%
addProviderTiles("Esri.WorldImagery", group = "Satellite") %>%
addPolygons(data = vicdata_sf, color = "blue", weight = 2, opacity = 0.7, fillOpacity = 0.3,
popup = ~paste("Victorian Structure:", STRUC_TYPE), group = "Victorian Structures") %>%
addPolygons(data = OSM_cps_sf, color = "red", weight = 2, opacity = 0.7, fillOpacity = 0.3,
popup = ~paste("OSM Structure Type:", filetype), group = "OSM Structures") %>%
addPolygons(data = tasdata_sf, color = "green", weight = 2, opacity = 0.7, fillOpacity = 0.3,
popup = ~paste("Tasmanian Structure:", INFTY2_TXT), group = "Tasmanian Structures") %>%
setView(lng = 144.35, lat = -38.15, zoom = 12) %>%
addLegend("topright", colors = c("blue", "red","green"), labels = c("Victorian Coastal Structures", "OSM Coastal Structures","Tasmanian Structures"), opacity = 1) %>%
addLayersControl(
baseGroups = c("OpenStreetMap", "Satellite"),
overlayGroups = c("Victorian Structures", "OSM Structures","Tasmanian Structures"),
options = layersControlOptions(collapsed = FALSE)
)